%%% модуль для приоритетных очередей
-module(priority_lists).
-export([new/1, push/3, pop/1, top/1, current_rang/1]).
%-export([get_current_list/1, get_list/2, get_rang_list/1]).
-export([test/0]).

test()->
    PL =  push(0, lol, push(1, hren, new(2))),
    top(PL).
    
    

%%% запись для представления приортиетных очередей
-record(plists, { rangLists = array:new(), % массив списков, индекс массива - ранг списка
		  max_rang  = 0,   %максимальный ранг
		  current_list =0,  %непустой список, минимальный по рангу. 
		  count_el =0      %количество элементов в очереди
		  }).


new(CountList) ->
    #plists{ rangLists    = array:new([{size,CountList+1},{default, []}]),
	     max_rang     = CountList,
	     current_list = 0}.
new(RangList, Max_rang, Current_List, Count_el) ->
    #plists{ rangLists    = RangList,
	     max_rang     = Max_rang,
	     current_list = Current_List,
	     count_el     = Count_el }.

get_rang_list(PList) ->
    PList#plists.rangLists.

get_current_list(PList) ->
    PList#plists.current_list.

get_max_rang(PList) ->
    PList#plists.max_rang.

get_count_el(PList) ->
    PList#plists.count_el.

push(Rang, Value, PList) ->
    Cl = get_current_list(PList),
    if
	Rang >= Cl -> 
	    new( array:set( Rang,
			    [Value] ++ get_list(Rang, PList),
			    get_rang_list(PList) ),
		 get_max_rang(PList),
		 min_N(Cl,Rang),
		 get_count_el(PList) + 1);
	true ->
	    new( array:set( Rang,
			    [Value],
			    get_rang_list(PList)),
		 get_max_rang(PList),
		 Rang,
		 get_count_el(PList) + 1)
     end.		 
    
top(PList) ->
     htop_list(get_list( get_current_list(PList),
			 PList)).

pop(PList) ->
    case get_list( get_current_list(PList), PList) of
	[_] ->
	    new( array:set( get_current_list(PList),
			    [],
			    get_rang_list(PList)),
		 get_max_rang(PList),
		 get_next_current_list(PList),
		 get_count_el(PList)-1);
	[A|_] ->
	    new( array:set( get_current_list(PList),
			    get_list( get_current_list(PList), PList) -- [A],
			    get_rang_list(PList)),
		 get_max_rang(PList),
		 get_current_list(PList),
		 get_count_el(PList)-1)
    end.

get_next_current_list(PList) ->
    CList = get_current_list(PList),
    Val   = get_max_rang(PList),
    if 
	CList < Val ->
	    case get_list(CList + 1, PList) of
		[] ->
		    0;
		[_] ->
		    CList+1
	    end;
	true -> Val
    end.
		 
current_rang(PList) ->
    get_current_list(PList).
    
get_list(Rang, PList) ->
    array:get(Rang, PList#plists.rangLists).

min_N(A,B) when A==0 ->
    B;
min_N(A,B) when B==0 ->
    A;
min_N(A,B) ->
    if
	A<B ->
	    A;
	true -> B
    end.

htop_list([A|_]) ->
    A.
